// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// r [author] rhyme_lph
// R [email]  rhymelph@gmail.com
// T [github] https://github.com/rhymelph

import 'dart:io';

import 'package:base_plugin/base_plugin.dart';
import 'package:camera/camera.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/services/edge_detection/edge_detector.dart';
import 'package:finance_app/services/mlv_service.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/widgets/bottom_sheet/ocr_tip_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/photo_no_clear_info_bottom_sheet.dart';
import 'package:finance_app/src/widgets/picture/normal_camera.dart';
import 'package:flutter/material.dart';
import 'package:my_edge_detection/edge_detection.dart';

class OCRCameraProvider extends BaseProvider {
  bool isSelectSingle = true;
  List<FlashMode> allFlashModel = [
    FlashMode.off,
    FlashMode.always,
  ];
  FlashMode currentFlashMode = FlashMode.off;
  GlobalKey<NormalCameraState> cameraKey = GlobalKey();
  List<String> takePathList = [];
  MLVService mlvService = MLVService();
  bool isSelect = false;
  bool activeOCR = true;

  @override
  Future get dataFuture => null;

  void onNavPicture() async {
    await cameraKey.currentState.stopStreaming();
    final result = await Routes.navigateTo(RouterGenProviders.selectPhotoPage,
        replace: isSelect != true,
        params: {
          'isSelect': isSelect,
        });
    if (result != null) {
      obtainContext?.call((context) {
        Navigator.of(context).pop(result);
      });
    }
  }

  void onClearTakePicture() {
    takePathList.forEach((element) {
      File(element).delete();
    });
    takePathList.clear();
  }

  void onDeleteLast() {
    File(takePathList.removeLast()).delete();
    update();
  }

  void onTakePicture() async {
    if (isSelectSingle == true) {
      obtainContext?.call((context) async {
        if (isSelect == true) {
          await cameraKey.currentState.stopStreaming();
          final picture = await cameraKey.currentState.takePicture();
          onNavToNextPage(picture.path);
        } else {
          BaseConfig.dialogBase
              .showLoadingDialog(context: context, text: S.current.loading);
          await cameraKey.currentState.stopStreaming();
          final picture = await cameraKey.currentState.takePicture();
          bool isClear = await mlvService.isCaptureClear(picture.path);
          if (isClear == false) {
            Navigator.of(context).pop();
            var result =
                await showPhotoNoClearInfoBottomSheet(context, onContinue: () {
              Navigator.of(context).pop(0);
              takePathList.add(picture.path);
              onNavToNextPage(picture.path);
            }, onRetake: () async {
              await cameraKey.currentState.startStream();
              onClearTakePicture();
              update();
              Navigator.of(context).pop(0);
            });
            if (result == null) {
              await cameraKey.currentState.startStream();
              onClearTakePicture();
              update();
            }
          } else {
            bool isCroppped = await autoCropPhoto(picture.path);
            print("isCropped : $isCroppped");
            onClearTakePicture();
            takePathList.add(picture.path);
            Navigator.of(context).pop();
            update();
            onNavToNextPage(picture.path);
          }
        }
      });
    } else {
      await cameraKey.currentState.stopStreaming();
      final picture = await cameraKey.currentState.takePicture();

      bool isCroppped = await autoCropPhoto(picture.path);
      print("isCropped : $isCroppped");
      await cameraKey.currentState.startStream();
      if (picture != null) {
        takePathList.add(picture.path);
        update();
      }
    }
  }

  Future<bool> autoCropPhoto(String filePath) async {
    if (!activeOCR || cameraKey.currentState.edgeDetectionResult == null)
      return false;
    EdgeDetectionResult edgeDetectionResult;
    edgeDetectionResult = await EdgeDetector().detectEdges(filePath);
    bool result =
        await EdgeDetector().processImage(filePath, edgeDetectionResult);
    if (result == false) {
      return result;
    }
    imageCache.clearLiveImages();
    imageCache.clear();

    return result;
  }

  void onNavToNextPage(String path) {
    if (isSelect == true) {
      obtainContext?.call((context) {
        Navigator.of(context).pop(path);
      });
    } else {
      Routes.navigateTo(RouterGenProviders.reviewPhotoPage,
          params: {
            'filepath': takePathList.join(','),
          },
          replace: true);
    }
  }

  void onNavInfo() {
    obtainContext?.call((context) {
      showOcrTipBottomSheet(context, onGotIt: () {
        Navigator.of(context).pop();
      });
    });
  }

  void onChangeFlash() {
    int index = allFlashModel.indexOf(currentFlashMode);
    if (index + 1 > allFlashModel.length - 1) {
      index = 0;
    } else {
      index++;
    }
    currentFlashMode = allFlashModel[index];
    update();
  }

  void onSelectSingle() {
    isSelectSingle = true;
    update();
  }

  void onSelectCombine() {
    isSelectSingle = false;
    update();
  }

  void onNavNextDetail() {
    Routes.navigateTo(RouterGenProviders.reviewPhotoPage,
        params: {
          'filepath': takePathList.join(','),
          'isCombine': true,
        },
        replace: true);
  }
}
